#include "UIL.h"

int CheckLoginTimes() {
	if (AllowedLoginTimes < LoginsTries) 
		return 1;
	else 
		return 0;
}

void ClearScreen() {
	system("cls");
}

int TestSystemLogin() {
	char username[50], password[100];
	int DelimCounter = 0, PrivlageRule;
	char* token;

	if (CheckLoginTimes()) {
		puts("You have reached the maximum allowed login tries\nThe program will now exit...\n");
		Sleep(3000);
		exit(1);
	}
	
	//! Login Details fields
	puts("Welcome Guest\nPlease Enter Your Username:");
	printf("User: "); gets(username);

	puts("\nPlease Enter Your Password:");
	printf("Pass: "); gets(password);

	//! Testing Login Details
	while (strlen(username)>50 || strlen(password)>100) {
		ClearScreen();

		puts("Your Entry is Invalid!");

		puts("\nPlease Enter Your Username:");
		printf("User: "); gets(username);

		puts("\nPlease Enter Your Password:");
		printf("Pass: "); gets(password);
	}

	//! Establishing Repository
	EstablishRepository("C:\\DATA\\");

	//! Testing UserDB file
	FILE* file = fopen(UserDB, "r");
	char line[256];

	if (file) {

		while (fgets(line, sizeof(line), file)) {

			/* gets the first token */
			token = strtok(line, DELIMITER);
			UT.UserName = token;
			++DelimCounter;

			/* test only if username is legit */
			if (strcmp(username, UT.UserName) == 0) {

				/* walk through other tokens */
				while (token != NULL)
				{
					token = strtok(NULL, DELIMITER);

					switch (DelimCounter) {
					case 1:
						UT.PassWord = token;
						break;
					case 2:
						PrivlageRule = atoi(token);

						//! Setting the correct position
						switch (PrivlageRule) {
						case 0:
							UT.UserPrivlage = Manager;
							break;
						case 1:
							UT.UserPrivlage = MainWarehouse;
							break;
						case 2:
							UT.UserPrivlage = ReceptionWarehouse;
							break;
						case 3:
							UT.UserPrivlage = Clerk;
							break;
						default:;
							//! puts("ERR: Unknown.");
						}
				
					default:;
						//! puts("ERR: Problem occured while try reading from UserDB file.");
					}

					++DelimCounter;
				}

			}
			else {
				//! Promotes raw token to the next user data
				while (token != NULL) token = strtok(NULL, DELIMITER);
			}

			//! Login Validation
			if ((strcmp(username, UT.UserName) == 0) && (strcmp(password, UT.PassWord) == 0))
			{
				puts("Loged in successfully!\n");
				Sleep(500);
				ClearScreen();
				fclose(file);

				return 1;
			}

			DelimCounter = 0;
		}

		fclose(file);
		system("cls");
		puts("** Wrong login credentials **");

		if (AllowedLoginTimes - LoginsTries > 0) 
		{ 
			printf("** You have %d login tries left. **\n", AllowedLoginTimes - LoginsTries); 
			puts("** Please Note, Password is case sensitive! **");
		}
		else
			printf("** You have no login tries left. **\n");
		

		++LoginsTries;
		Sleep(4000);

		return 0;
	}
	return 1;
}

void WelcomeMessage() {
	printf("Hello %s (", UT.UserName);

	switch (UT.UserPrivlage) {
	case 0:
		printf("Manager");
		break;
	case 1:
		printf("MainWarehouse");
		break;
	case 2:
		printf("ReceptionWarehouse");
		break;
	case 3:
		printf("Clerk");
		break;
	}
	printf("),\nChoose one of the following options:\n\n");
}

void PrintMainMenuOptions() {
	puts("** Main Menu **\n");
	puts("1. Product Actions\n2. Search Item\n3. Delivery Zones Managment\n4. Supplier Management\n5. Customer Management\n6. Delivery Batch Managment\n7. Supply Batch Managment\n0. Exit\n");
}

void PrintProductOptions() {
	puts("** Product Managment Menu **\n");
	puts("1. Add Product Record\n2. Remove Product Record\n3. Print Product Record\n0. Back to Main Menu\n");
}

void PrintSearchOptions() {
	puts("** Search Options Menu **\n");
	puts("1. Print Details of Product by ID\n2. Print Details of Product by Name\n0. Back to Main Menu\n");
}

void PrintZonesOptions() {
	puts("** Delivery Zone Options Menu **\n");
	puts("1. Add Zone record\n2. Remove Zone record\n3. Print All Zone record\n0. Back to Main Menu\n");
}

void PrintSupplierOptions() {
	puts("** Supplier Options Menu **\n");
	puts("1. Add Supplier record\n2. Remove Supplier record\n3. Search Supplier by Name\n4. Print All Suppliers record\n0. Back to Main Menu\n");
}

void PrintCustomerOptions() {
	puts("** Customer Options Menu **\n");
	puts("1. Add Customer record\n2. Remove Customer record\n3. Search Customer by Name\n4. Print All Customers record\n0. Back to Main Menu\n");
}

void PrintDeliveryBatchOptions() {
	puts("** Delivery Batch Managment **\n");
	puts("1. Create Delivery Batch\n2. Load Pending Delivery batches\n3. Dispatch Delivery batches\n4. Complete Delivery batches\n0. Back to Main Menu\n");
}

void PrintSupplyBatchOptions() {
	puts("** Supply Batch Managment **\n");
	puts("1. Create Supply Batch\n2. Unload Supply Batch\n3. Complete Supply Batch\n0. Back to Main Menu\n");
}

void PrintManagmentOptions() {
	puts("** Managment Options Menu **\n");
	puts("1. Users Managment\n2. Print System Logs\n3. Import System DB's\n4. Export System DB's\n0. Back to Main Menu\n");
}

void PrintUserManagmentOptions() {
	puts("** Managment Options :: User Managment **\n");
	puts("1. Add User records\n2. Remove User records\n0. Back to Main Menu\n");
}

//! This function testing user option value.
//! In case there's a problem with the input return's Defective indicator. 
int GetUserOption(int val, unsigned int menu) 
{
	char* ErrMsg = "Entry is incorrect, please try again";
	printf("Option: ");
	scanf("%d", &val);

	//! Rules of each Menu input
	switch (menu) {
	case 0:
		//! Main Menu Options
		if (val > 7 || val < 0)
		{
			puts(ErrMsg);
			return DEFECTIVEUSERENTRY;
		}
		break;
	case 1:
		//! Product Actions
		if (val > 3 || val < 0)
		{
			puts(ErrMsg);
			return DEFECTIVEUSERENTRY;
		}
		break;
	case 2:
		//! Search Options
		if (val > 2 || val < 0)
		{
			puts(ErrMsg);
			return DEFECTIVEUSERENTRY;
		}
		break;
	case 3:
		//! Zones Managment
		if (val > 3 || val < 0)
		{
			puts(ErrMsg);
			return DEFECTIVEUSERENTRY;
		}
		break;
	case 4:
		//! Supplier Managment
		if (val > 4 || val < 0)
		{
			puts(ErrMsg);
			return DEFECTIVEUSERENTRY;
		}
		break;
	case 5:
		//! Customer Managment
		if (val > 4 || val < 0)
		{
			puts(ErrMsg);
			return DEFECTIVEUSERENTRY;
		}
		break;
	case 6:
		//! Delivery Batch Managment
		if (val > 4 || val < 0)
		{
			puts(ErrMsg);
			return DEFECTIVEUSERENTRY;
		}
		break;
	case 7:
		//! Supply Batch Managment
		if (val > 3 || val < 0)
		{
			puts(ErrMsg);
			return DEFECTIVEUSERENTRY;
		}
		break;
	case 8:
		//! System Managment
		//! For Expanding the System
		if (val > 4 || val < 0)
		{
			puts(ErrMsg);
			return DEFECTIVEUSERENTRY;
		}
		break;
	case 9:
		//! User Managment
		if (val > 2 || val < 0)
		{
			puts(ErrMsg);
			return DEFECTIVEUSERENTRY;
		}
		break;

	default:
		//! No defaults needed.
		break;
	}

	return val;
}

void AddProductUI()
{
	char buffer[250];
	unsigned int quantity=0, ReturnedVal=0;

	while (getchar() == '/n');

	printf("Please Enter the Product Name: ");
	fgets(buffer, 200, stdin);

	/* Remove trailing newline, if there. */
	if ((strlen(buffer)>0) && (buffer[strlen(buffer) - 1] == '\n'))
		buffer[strlen(buffer) - 1] = '\0';

	printf("Enter Existing Quantaties: ");
	scanf("%d", &quantity);

	ReturnedVal = AddProduct(buffer, quantity);
	
	printf("The Product ID is: %u\n", ReturnedVal);
	
	system("pause");
}

void DeleteProductUI()
{
	unsigned int id = 0;

	while (getchar() == '/n');

	printf("Enter The Product ID to be deleted: ");
	scanf("%u", &id);

	Product checkProduct = GetProduct(id);

	if (checkProduct.ID)
	{
		DeleteProduct(id);
		free(checkProduct.Name);
		printf("Product deleted.\n");
	}
	else
		printf("Product does not exist.\n");

	system("pause");
}
void SearchProductByNameUI()
{
	int i = 0, MaxID = GetMaximalIDForProduct();
	char buffer[1000];

	while (getchar() == '/n');

	printf("Enter the Product Name to be found: ");
	fgets(buffer, 200, stdin);

	buffer[strlen(buffer)-1] = NULL;

	for (i = 1; i <= MaxID; i++)
	{
		Product p = GetProduct(i);

		if (p.ID)
		{
			if (_strcmpi(p.Name, buffer) == 0)
			{
				printf("Result Found. Name: %s. ID: %u. Inventory: %u.\n", p.Name, p.ID, p.Inventory);
			}
		}

		free(p.Name);
	}
	system("pause");
}
void SearchProductByIdUI() 
{
	unsigned int ProductId = 0;
	while (getchar() == '/n');

	printf("Please Enter Product ID: ");
	scanf("%u",&ProductId);

	Product p = GetProduct(ProductId);

	if (p.ID)
	{
		printf("Name: %s. ID: %u. Inventory: %u.\n", p.Name, p.ID, p.Inventory);
		free(p.Name);
	}
	 else 
		printf("No such Product.\n");

	system("pause");
}
void ViewAllProductsUI()
{
	int i = 0, MaxID = GetMaximalIDForProduct();
	
	for (i = 1; i <= MaxID; i++)
	{
		Product p = GetProduct(i);

		if (p.ID)
		{
			printf("Name: %s. ID: %u. Inventory: %u.\n", p.Name, p.ID, p.Inventory);
			free(p.Name);
		}
	}
	system("pause");
}
void AddRegionUI() {
	char buffer[250];
	unsigned int ReturnedVal = 0;

	while (getchar() == '/n');

	printf("Please Enter the Region Name: ");
	fgets(buffer, 200, stdin);

	/* Remove trailing newline, if there. */
	if ((strlen(buffer)>0) && (buffer[strlen(buffer) - 1] == '\n'))
		buffer[strlen(buffer) - 1] = '\0';

	ReturnedVal = AddRegion(buffer);

	printf("The Region ID is: %u\n", ReturnedVal);
	system("pause");
}

void DeleteRegionUI()
{
	unsigned int id = 0;

	while (getchar() == '/n');

	printf("Enter The Region ID to be deleted: ");
	scanf("%u", &id);

	Region checkRegion = GetRegion(id);

	if (checkRegion.ID)
	{
		DeleteRegion(id);
		free(checkRegion.Name);
		printf("Region deleted.\n");
	}
	else
		printf("Region does not exist.\n");

	system("pause");
}


void ViewAllRegionsUI()
{
	int i = 0, MaxID = GetMaximalIDForRegion();

	for (i = 1; i <= MaxID; i++)
	{
		Region p = GetRegion(i);

		if (p.ID)
		{
			printf("Name: %s. ID: %u.\n", p.Name, p.ID);
			free(p.Name);
		}
	}
	system("pause");
}
void AddCustomerUI()
{
	char bufferA[200], bufferB[200];
	unsigned int CustomerID = 0, regionID;
	
	while (getchar() == '/n');

	printf("Please Enter the Customer Name: ");
	fgets(bufferA, 200, stdin);

	/* Remove trailing newline, if there. */
	if ((strlen(bufferA)>0) && (bufferA[strlen(bufferA) - 1] == '\n'))
		bufferA[strlen(bufferA) - 1] = '\0';

	printf("Please Enter the Customer Contact Information: ");
	fgets(bufferB, 200, stdin);

	printf("Enter the Customer Region ID: ");
	scanf("%u", &regionID);
	
	Region R = GetRegion(regionID);

	if (R.ID == 0) regionID = 0;
	else free(R.Name);

	/* Remove trailing newline, if there. */
	if ((strlen(bufferB)>0) && (bufferB[strlen(bufferB) - 1] == '\n'))
		bufferB[strlen(bufferB) - 1] = '\0';

	CustomerID = AddCustomer(regionID, bufferA, bufferB);

	printf("Customer ID is: %u.\n", CustomerID);

	system("pause");
}
void DeleteCustomerByIdUI()
{
	unsigned int id = 0;

	while (getchar() == '/n');

	printf("Enter The Customer ID to be deleted: ");
	scanf("%u", &id);

	Customer checkCustomer = GetCustomer(id);

	if (checkCustomer.ID)
	{
		DeleteContact(checkCustomer.ContactID);
		DeleteCustomer(id);
		printf("Customer deleted.\n");
	}
	else
		printf("Customer does not exist.\n");

	system("pause");
}
void SearchCustomerByNameUI()
{
	int i = 0, MaxID = GetMaximalIDForCustomer();
	char buffer[1000];

	while (getchar() == '/n');

	printf("Enter the Customer Name to be found: ");
	fgets(buffer, 200, stdin);

	buffer[strlen(buffer) - 1] = NULL;

	for (i = 1; i <= MaxID; i++)
	{
		Customer p = GetCustomer(i);

		if (p.ID)
		{
			Contact c = GetContact(p.ContactID);
			Region r = GetRegion(p.RegionID);
			if (r.ID == 0)
				r.Name = "Default Region";

			if (_strcmpi(c.Name, buffer) == 0)
			{
				printf("Result Found. Name: %s. ID: %u. Contact Info: %s. Region: %s.\n", c.Name, p.ID, c.ContactInformation, r.Name);
			}

			free(c.Name);
			free(c.ContactInformation);
			if (r.ID != 0) free(r.Name);
		}
	}
	system("pause");

}
void ViewAllCustomersUI()
{
	int i = 0, MaxID = GetMaximalIDForCustomer();

	for (i = 1; i <= MaxID; i++)
	{
		Customer p = GetCustomer(i);

		if (p.ID)
		{
			Contact c = GetContact(p.ContactID);
			Region r = GetRegion(p.RegionID);
			
			if (r.ID == 0) r.Name = "Default Region";

			printf("Result Found. Name: %s. ID: %u. Contact Info: %s. Region: %s.\n", c.Name, p.ID, c.ContactInformation, r.Name);
	
			free(c.Name);
			free(c.ContactInformation);
			
			if (r.ID != 0) free(r.Name);
		}
	}
	system("pause");

}
void AddSupplierUI()
{
	char bufferA[200], bufferB[200];
	int SuppID=0;
	while (getchar() == '/n');

	printf("Please Enter the Supplier Name: ");
	fgets(bufferA, 200, stdin);

	/* Remove trailing newline, if there. */
	if ((strlen(bufferA)>0) && (bufferA[strlen(bufferA) - 1] == '\n'))
		bufferA[strlen(bufferA) - 1] = '\0';

	printf("Please Enter the Supplier Contact Information: ");
	fgets(bufferB, 200, stdin);

	/* Remove trailing newline, if there. */
	if ((strlen(bufferB)>0) && (bufferB[strlen(bufferB) - 1] == '\n'))
		bufferB[strlen(bufferB) - 1] = '\0';

	SuppID = AddSupplier(bufferA, bufferB);

	printf("Supplier ID is: %u.\n", SuppID);

	system("pause");
}
void SearchSupplierByNameUI()
{
	unsigned int i = 0, MaxID = GetMaximalIDForSupplier();
	char buffer[1000];

	while (getchar() == '/n');

	printf("Enter the Supplier Name to be found: ");
	fgets(buffer, 200, stdin);

	buffer[strlen(buffer) - 1] = NULL;

	for (i = 1; i <= MaxID; i++)
	{
		Supplier p = GetSupplier(i);
		
		if (p.ID)
		{
			Contact c = GetContact(p.ContactID);

			if (_strcmpi(c.Name, buffer) == 0)
			{
				printf("Result Found. Name: %s. ID: %u. Contact Info: %s.\n", c.Name, p.ID, c.ContactInformation);
			}

			free(c.Name);
			free(c.ContactInformation);
		}
	}
	system("pause");

}
void ViewAllSuppliersUI()
{
	int i = 0, MaxID = GetMaximalIDForSupplier();

	for (i = 1; i <= MaxID; i++)
	{
		Supplier p = GetSupplier(i);

		if (p.ID)
		{
			Contact c = GetContact(p.ContactID);

			printf("Supplier Name: %s. Supplier ID: %u. Contact Info: %s.\n", c.Name, p.ID, c.ContactInformation);
			
			free(c.Name);
			free(c.ContactInformation);
		}
	}
	system("pause");

}
void DeleteSupplierByIdUI()
{
	unsigned int id = 0;
	while (getchar() == '/n');

	printf("Enter The Supplier ID to be deleted: ");
	scanf("%u", &id);

	Supplier checkSupplier = GetSupplier(id);

	if (checkSupplier.ID)
	{
		DeleteContact(checkSupplier.ContactID);
		DeleteSupplier(id);
		printf("Supplier deleted.\n");
	}
	else
		printf("Supplier does not exist.\n");

	system("pause");
}

void AddDeliveryBatchUI()
{
	unsigned int id = 0, ProductNum = 0, i = 0;
	unsigned int DeliveriesIdsBuffer[16];
	char buffer[1000];
	Delivery DeliveriesBuffer[15];
	DeliveryBatch DB;

	for (i = 0; i < 15; i++) {
		DeliveriesBuffer[i].ProductID = 0;
		DeliveriesBuffer[i].ID = 0;
		DeliveriesBuffer[i].Amount = 0;
	}

	while (getchar() == '/n');

	printf("Enter The Customer to Deliver to by ID: ");
	scanf("%u", &id);

	Customer checkCustomer;
	checkCustomer = GetCustomer(id);

	if (checkCustomer.ID==0)
	{
		printf("Customer does not exist.\nExiting...\n");
		system("pause");
		return;
	}

	printf("Enter the Number of products to be delivered (MAX 15): ");
	scanf("%u", &ProductNum);

	if ((ProductNum == 0) || (ProductNum > 15)) {
		
		printf("Invalid Number of Products\nExiting...\n");
		system("pause");
		return;
	}

	for (i = 0; i < ProductNum; i++) {
		unsigned int ProductID, j, Amount;
		Delivery NewDelivery;
		Product p;
		
		tryagain:

		printf("Enter Product ID to Deliver (0 to abort): ");
		scanf("%u", &ProductID);
		
		if (ProductID == 0) {
			printf("Exiting back to MainMenu\n");
			system("pause");
			return;
		}
		p = GetProduct(ProductID);
		free(p.Name);

		if (p.ID == 0) {
			printf("Product does not exist\nTry again.\n");
			goto tryagain;
		}

		for (j = 0; j < i; j++) {
			if (DeliveriesBuffer[j].ProductID == p.ID) {
				printf("Product already in batch!\nTry again.\n");
				goto tryagain;
			}
		}

		DeliveriesBuffer[i].ProductID = ProductID;
		
		tryagain2:

		printf("Enter the Amount to Deliver: ");
		scanf("%u", &Amount);

		if (Amount == 0) {
			printf("Amount needs to be greater than zero.\nTry Again\n");
			goto tryagain2;
		}

		DeliveriesBuffer[i].Amount = Amount;		
	}

	for (i = 0; i < ProductNum; i++) {
		DeliveriesIdsBuffer[i] = AddDelivery(DeliveriesBuffer[i].ProductID, DeliveriesBuffer[i].Amount);
	} 

	DeliveriesIdsBuffer[i] = 0;
	DB.CustomerID = checkCustomer.ID;
	DB.DeliveriesIDs = DeliveriesIdsBuffer;
	DB.Status = DELIVERY_PENDING;
	DB.DueDate = "NA";
	DB.ID = GetAvailableIDForDeliveryBatch();
	
	SetDeliveryBatch(DB);

}

void LoadDeliveriesUI() {
	int i = 0, MaxID = GetMaximalIDForDeliveryBatch();
	unsigned int id;
	for (i = 1; i <= MaxID; i++)
	{
		DeliveryBatch p = GetDeliveryBatch(i);

		if (p.ID)
		{
			if (p.Status == DELIVERY_PENDING) {
				Customer c;
				Contact co;
				
				c = GetCustomer(p.CustomerID);
				co = GetContact(c.ContactID);

				printf("Delivery for Customer: %s. ID: %u. is PENDING\n", co.Name, p.ID);
				free(co.Name);
				free(co.ContactInformation);
			}
		}
	}

	printf("Which Delivery Batch do you wish to Load?\n");
	scanf("%u", &id);

	{
		DeliveryBatch DB = GetDeliveryBatch(id);
		if ((DB.ID == 0) || (DB.Status!=DELIVERY_PENDING)) {
			printf("The id does not exist\nExiting...\n");
			system("pause");
			return;
		}
		i = 0;
		while (DB.DeliveriesIDs[i]) {
			Product PR;
			Delivery ThisDelivery = GetDelivery(DB.DeliveriesIDs[i]);
			PR = GetProduct(ThisDelivery.ProductID);
			
			if (PR.Inventory < ThisDelivery.Amount) {
				printf("Delivery Batch cannot be loaded.\nInsufficiant %s in inventory", PR.Name);
				system("pause");
				return;
			}
			free(PR.Name);
		}

		i = 0;
		while (DB.DeliveriesIDs[i]!=NULL) {
			Product PR;
			Delivery ThisDelivery = GetDelivery(DB.DeliveriesIDs[i]);
			PR = GetProduct(ThisDelivery.ProductID);
			//Removing products from the warehouse
			PR.Inventory -= ThisDelivery.Amount;

			SetProduct(PR);
			free(PR.Name);
			i++;
		}
		DB.Status = DELIVERY_LOADED;
		SetDeliveryBatch(DB);

		printf("Items Loaded.\n");

	}

	system("pause");
}

void DispachDeliveriesUI() {
	int i = 0, MaxID = GetMaximalIDForDeliveryBatch();
	unsigned int id;
	for (i = 1; i <= MaxID; i++)
	{
		DeliveryBatch p = GetDeliveryBatch(i);

		if (p.ID)
		{
			if (p.Status == DELIVERY_LOADED) {
				Customer c;
				Contact co;

				c = GetCustomer(p.CustomerID);
				co = GetContact(c.ContactID);

				printf("Delivery for Customer: %s. ID: %u. is LOADED\n", co.Name, p.ID);
				free(co.Name);
				free(co.ContactInformation);
			}
		}
	}

	printf("Which Delivery Batch do you wish to Dispatch?\n");
	scanf("%u", &id);

	{
		DeliveryBatch DB = GetDeliveryBatch(id);
		if ((DB.ID == 0) || (DB.Status != DELIVERY_LOADED)) {
			printf("The id does not exist\nExiting...\n");
			system("pause");
			return;
		}
	
		DB.Status = DELIVERY_DISPATCHED;
		SetDeliveryBatch(DB);

		printf("Items Dispatched.\n");

	}

	system("pause");
}

void CompleteDeliveriesUI() {
	int i = 0, MaxID = GetMaximalIDForDeliveryBatch();
	unsigned int id;
	for (i = 1; i <= MaxID; i++)
	{
		DeliveryBatch p = GetDeliveryBatch(i);

		if (p.ID)
		{
			if (p.Status == DELIVERY_DISPATCHED) {
				Customer c;
				Contact co;

				c = GetCustomer(p.CustomerID);
				co = GetContact(c.ContactID);

				printf("Delivery for Customer: %s. ID: %u. is DISPACHED\n", co.Name, p.ID);
				free(co.Name);
				free(co.ContactInformation);
			}
		}
	}

	printf("Which Delivery Batch do you wish to Complete?\n");
	scanf("%u", &id);

	{
		DeliveryBatch DB = GetDeliveryBatch(id);
		if ((DB.ID == 0) || (DB.Status != DELIVERY_DISPATCHED)) {
			printf("The id does not exist\nExiting...\n");
			system("pause");
			return;
		}

		DB.Status = DELIVERY_DONE;
		SetDeliveryBatch(DB);

		printf("Delivery Batch Completed.\n");

	}

	system("pause");
}

void AddSupplyBatchUI() 
{
	unsigned int id = 0, ProductNum = 0, i = 0;
	unsigned int SuppliesIdsBuffer[16];
	char buffer[1000];
	Supply DeliveriesBuffer[15];
	SupplyBatch SB;

	for (i = 0; i < 15; i++) {
		DeliveriesBuffer[i].ProductID = 0;
		DeliveriesBuffer[i].ID = 0;
		DeliveriesBuffer[i].Amount = 0;
	}

	while (getchar() == '/n');

	printf("Enter The Supplier who Supplies us by ID: ");
	scanf("%u", &id);

	Supplier checkSupplier;
	checkSupplier = GetSupplier(id);

	if (checkSupplier.ID == 0)
	{
		printf("Supplier does not exist.\nExiting...\n");
		system("pause");
		return;
	}

	printf("Enter the Number of products to be supplied (MAX 15): ");
	scanf("%u", &ProductNum);

	if ((ProductNum == 0) || (ProductNum > 15)) {

		printf("Invalid Number of Products\nExiting...\n");
		system("pause");
		return;
	}

	for (i = 0; i < ProductNum; i++) {
		unsigned int ProductID, j, Amount;
		Supply NewSupply;
		Product p;

	tryagain:

		printf("Enter Product ID to Supply (0 to abort): ");
		scanf("%u", &ProductID);

		if (ProductID == 0) return;

		p = GetProduct(ProductID);
		free(p.Name);

		if (p.ID == 0) {
			printf("Product does not exist\nTry again.\n");
			goto tryagain;
		}

		for (j = 0; j < i; j++) {
			if (DeliveriesBuffer[j].ProductID == p.ID) {
				printf("Product already in batch!\nTry again.\n");
				goto tryagain;
			}
		}

		DeliveriesBuffer[i].ProductID = ProductID;

	tryagain2:

		printf("Enter the Amount to Supply: ");
		scanf("%u", &Amount);

		if (Amount == 0) {
			printf("Amount needs to be greater than zero.\nTry Again\n");
			goto tryagain2;
		}

		DeliveriesBuffer[i].Amount = Amount;
	}

	for (i = 0; i < ProductNum; i++) {
		SuppliesIdsBuffer[i] = AddSupply(DeliveriesBuffer[i].ProductID, DeliveriesBuffer[i].Amount);
	}

	SuppliesIdsBuffer[i] = 0;
	SB.SupplierID = checkSupplier.ID;
	SB.SuppliesIDs = SuppliesIdsBuffer;
	SB.Status = SUPPLY_PENDING;
	SB.ID = GetAvailableIDForSupplyBatch();

	SetSupplyBatch(SB);

}

void UnLoadSuppliesBatchUI() {
	int i = 0, MaxID = GetMaximalIDForSupplyBatch();
	unsigned int id;
	for (i = 1; i <= MaxID; i++)
	{
		SupplyBatch p = GetSupplyBatch(i);

		if (p.ID)
		{
			if (p.Status == SUPPLY_PENDING) {
				Supplier c;
				Contact co;

				c = GetSupplier(p.SupplierID);
				co = GetContact(c.ContactID);

				printf("Supply from Supplier: %s. ID: %u. is PENDING\n", co.Name, p.ID);
				free(co.Name);
				free(co.ContactInformation);
			}
		}
	}

	printf("Which Supply Batch do you wish to Unload?\n");
	scanf("%u", &id);

	{
		SupplyBatch SB = GetSupplyBatch(id);
		if ((SB.ID == 0) || (SB.Status != SUPPLY_PENDING)) {
			printf("The id does not exist\nExiting...\n");
			return;
		}
	
		i = 0;
		while (SB.SuppliesIDs[i]!=NULL) {
			Product PR;
			Supply ThisSupply = GetSupply(SB.SuppliesIDs[i]);
			PR = GetProduct(ThisSupply.ProductID);
			//Adding products to the warehouse
			PR.Inventory += ThisSupply.Amount;

			SetProduct(PR);
			free(PR.Name);
			i++;
		}
		SB.Status = SUPPLY_UNLOADED;
		SetSupplyBatch(SB);

		printf("Items Unloaded.\n");

	}

	system("pause");
}

void CompleteSuppliesBatchUI() {
	int i = 0, MaxID = GetMaximalIDForSupplyBatch();
	unsigned int id;
	for (i = 1; i <= MaxID; i++)
	{
		SupplyBatch p = GetSupplyBatch(i);

		if (p.ID)
		{
			if (p.Status == SUPPLY_UNLOADED) {
				Supplier c;
				Contact co;

				c = GetSupplier(p.SupplierID);
				co = GetContact(c.ContactID);

				printf("Supply from Supplier: %s. ID: %u. is UNLOADED\n", co.Name, p.ID);
				free(co.Name);
				free(co.ContactInformation);
			}
		}
	}

	printf("Which Supply Batch do you wish to Complete?\n");
	scanf("%u", &id);

	{
		SupplyBatch SB = GetSupplyBatch(id);
		if ((SB.ID == 0) || (SB.Status != SUPPLY_UNLOADED)) {
			printf("The id does not exist\nExiting...\n");
			return;
		}

		SB.Status = SUPPLY_DONE;
		SetSupplyBatch(SB);

		printf("Supply Batch Completed.\n");

	}

	system("pause");
}


//! Program Dynamic Menu Stracture
int Menu()
{
	int UserOption = 1, TimesCycle = 0;
	unsigned int SubUserOption=0;
	unsigned int SubSubUserOption = 0;

	while (UserOption!=0) {

		if (TimesCycle != 0) ClearScreen();

		TimesCycle++;

		PrintMainMenuOptions();
		UserOption = GetUserOption(UserOption, 0);

		//! Testing User Entry Scope
		while (UserOption == DEFECTIVEUSERENTRY) UserOption = GetUserOption(UserOption, 0);

		switch (UserOption)
		{
		case 1:
			//! Product Actions
			ClearScreen();
			PrintProductOptions();
			SubUserOption = GetUserOption(SubUserOption, 1);
			while (SubUserOption == DEFECTIVEUSERENTRY) SubUserOption = GetUserOption(SubUserOption, 1);
			
			switch (SubUserOption)
			{
			case 1:
				//! Add Product
				if (UT.UserPrivlage == 3) {
					puts("Insufficient Privileges");
					system("pause");
					break;
				}
				AddProductUI();
				
				break;
			case 2:
				//! Remove Product
				if (UT.UserPrivlage == 3) {
					puts("Insufficient Privileges");
					system("pause");
					break;
				}
				DeleteProductUI();

				break;
			case 3:
				//! Print Product Details
				ViewAllProductsUI();
				break;
			default:
				break;
			}

			break;

		case 2:
			//! Search Items
			ClearScreen();
			PrintSearchOptions();
			SubUserOption = GetUserOption(SubUserOption, 2);
			while (SubUserOption == DEFECTIVEUSERENTRY) SubUserOption = GetUserOption(SubUserOption, 2);

			switch (SubUserOption)
			{
			case 1:
				//! Search by ID
				SearchProductByIdUI();
				break;
			case 2:
				//! Search by Client Name
				SearchProductByNameUI();
				break;
			default:
				break;
			}

			break;

		case 3:
			//! Delivery Zones Managment (Regions)
			ClearScreen();
			PrintZonesOptions();
			SubUserOption = GetUserOption(SubUserOption, 3);
			while (SubUserOption == DEFECTIVEUSERENTRY) SubUserOption = GetUserOption(SubUserOption, 3);

			switch (SubUserOption)
			{
			case 1:
				//! Add New Region
				AddRegionUI();
				break;
			case 2:
				//! Remove Region
				DeleteRegionUI();
				break;
			case 3:
				//! Print All Regions				
				ViewAllRegionsUI();
				break;
			default:
				break;
			}

			break;

		case 4:
			//! Supplier Management
			ClearScreen();
			PrintSupplierOptions();
			SubUserOption = GetUserOption(SubUserOption, 4);
			while (SubUserOption == DEFECTIVEUSERENTRY) SubUserOption = GetUserOption(SubUserOption, 4);

			switch (SubUserOption)
			{
			case 1:
				//! Add New Supplier
				if (UT.UserPrivlage == 3) {
					puts("Insufficient Privileges");
					system("pause");
					break;
				}
				AddSupplierUI();
				break;
			case 2:
				//! Remove Supplier
				if (UT.UserPrivlage == 3) {
					puts("Insufficient Privileges");
					system("pause");
					break;
				}
				DeleteSupplierByIdUI();
				break;
			case 3:
				//! Search Supplier by Name
				SearchSupplierByNameUI();
				break;
			case 4:
				//! Print All Supplier list
				ViewAllSuppliersUI();
				break;
			default:
				break;
			}

			break;
		case 5:
			//! Customer Management
			ClearScreen();
			PrintCustomerOptions();
			SubUserOption = GetUserOption(SubUserOption, 5);
			while (SubUserOption == DEFECTIVEUSERENTRY) SubUserOption = GetUserOption(SubUserOption, 5);

			switch (SubUserOption)
			{
			case 1:
				//! Add New Customer
				AddCustomerUI();
				break;
			case 2:
				//! Remove Customer
				DeleteCustomerByIdUI();
				break;
			case 3:
				//! Search Customer by Name
				SearchCustomerByNameUI();
				break;
			case 4:
				//! Print All Customer list
				ViewAllCustomersUI();
				break;
			default:
				break;
			}

			break;
		case 6:
			//! Delivery Batch Managment
			ClearScreen();
			PrintDeliveryBatchOptions();
			SubUserOption = GetUserOption(SubUserOption, 6);
			while (SubUserOption == DEFECTIVEUSERENTRY) SubUserOption = GetUserOption(SubUserOption, 6);

			switch (SubUserOption)
			{
			case 1:
				//! Create Delivery Batch
				if (UT.UserPrivlage == 3) {
					puts("Insufficient Privileges");
					system("pause");
					break;
				}
				AddDeliveryBatchUI();
				break;
			case 2:
				//! Load Pending Delivery batches
				if (UT.UserPrivlage == 3) {
					puts("Insufficient Privileges");
					system("pause");
					break;
				}
				LoadDeliveriesUI();
				break;
			case 3:
				//! Dispatch Delivery batches
				if (UT.UserPrivlage == 3) {
					puts("Insufficient Privileges");
					system("pause");
					break;
				}
				DispachDeliveriesUI();
				break;
			case 4:
				//! Complete Delivery batches
				if (UT.UserPrivlage == 3) {
					puts("Insufficient Privileges");
					system("pause");
					break;
				}
				CompleteDeliveriesUI();
				break; 
			default:
				break;
			}

			break;
		case 7:
			//! Supply Batch Managment
			ClearScreen();
			PrintSupplyBatchOptions();
			SubUserOption = GetUserOption(SubUserOption, 7);
			while (SubUserOption == DEFECTIVEUSERENTRY) SubUserOption = GetUserOption(SubUserOption, 7);

			switch (SubUserOption)
			{
			case 1:
				//! Create Supply Batch
				if (UT.UserPrivlage == 3) {
					puts("Insufficient Privileges");
					system("pause");
					break;
				}
				AddSupplyBatchUI();
				break;
			case 2:
				//! Unload Supply Batch
				if (UT.UserPrivlage == 3) {
					puts("Insufficient Privileges");
					system("pause");
					break;
				}
				UnLoadSuppliesBatchUI();
				break;
			case 3:
				//! Complete Supply Batch
				if (UT.UserPrivlage == 3) {
					puts("Insufficient Privileges");
					system("pause");
					break;
				}
				CompleteSuppliesBatchUI();
				break;
			default:
				break;
			}

			break;

		case 0:
			//! Exiting System. If there's need to free things this is the place:

			FinalizeRepository(); 
			puts("\nExiting the system,\nPlease be patient...");
			Sleep(2000);
			exit(1);

			break;

		}
	}


	return 1;
}